﻿/******************************************************
* author :  cwj
* email  :  chenwenji_360@live.com 
* history:  created by cwj 2015/7/16 16:28:41 
* clrversion :4.0.30319.18444
******************************************************/

using Machine.DataAccess.Common.ORM;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using Machine.DataAccess.Transaction;
using System.Diagnostics;
//using System.Threading;

namespace Machine.DataAccess.Linq
{
    internal static class DataResult
    {
        public static TResult GetResult<TResult>(TranslateResult translatResult, ProviderElement providerElement, CommandType commandType = CommandType.Text)
        {
            //Trace.WriteLine(string.Format("执行SQL:{0}", translatResult.SqlText));
            //var constr = Config.Instance.DefaultProvider.ConnectionString;//ConfigurationManager.ConnectionStrings["test"].ConnectionString;
            var typeCode = new OrmHelper().GetTypeCode(typeof(TResult));
            var factory = DbProviderFactories.GetFactory(providerElement.Provider);

            if (DataAccessExecutionContext.Current == null || DataAccessExecutionContext.Current.ProviderElement.Key != providerElement.Key)
            {
                using (DbConnection con = factory.CreateConnection())
                {
                    con.ConnectionString = providerElement.ConnectionString;//Config.Instance.DefaultProvider.ConnectionString;
                    con.Open();
                    using (DbCommand command = con.CreateCommand())
                    {
                        command.CommandText = translatResult.SqlText;
                        command.CommandType = commandType;
                        command.Parameters.AddRange((translatResult.Parameters as IEnumerable<DbParameter>).ToArray());
                        //if (typeCode == OrmType.KnowType || typeCode == OrmType.UnKnowType)
                        //{
                        using (var reader = command.ExecuteReader())
                        {
                            if (reader.HasRows && reader.Read())
                            {
                                var temp = new OrmHelper().GetResult<TResult>(reader, providerElement, typeCode);
                                reader.Close();
                                return temp;
                            }
                            else return default(TResult);
                        }
                        //}
                        //else if (typeCode == OrmType.Basic)
                        //{
                        //    var result = command.ExecuteScalar();
                        //    return result == null ? default(TResult) : (TResult)OrmHelper.GetBasic<TResult>(result);
                        //}//new OrmHelper().GetResult<TResult>(command.ExecuteScalar(), typeCode);
                        throw new NotSupportedException("暂不支持匿名类型");
                    }
                }
            }
            else
            {
                var con = DataAccessExecutionContext.Current.DbConnection;
                if (con.State != ConnectionState.Open) con.Open();
                using (DbCommand command = con.CreateCommand())
                {
                    command.CommandText = translatResult.SqlText;
                    command.CommandType = commandType;
                    command.Transaction = DataAccessExecutionContext.Current.Transaction;
                    command.Parameters.AddRange(translatResult.Parameters.ToArray());
                    //if (typeCode == OrmType.KnowType || typeCode == OrmType.UnKnowType)
                    //{
                    using (var reader = command.ExecuteReader())
                    {
                        if (reader.HasRows && reader.Read())
                        {
                            var temp = new OrmHelper().GetResult<TResult>(reader, providerElement, typeCode);
                            reader.Close();
                            return temp;
                        }
                        else return default(TResult);
                    }
                    //}
                    //else if (typeCode == OrmType.Basic)
                    //{
                    //    var result = command.ExecuteScalar();
                    //    return result == null ? default(TResult) : (TResult)OrmHelper.GetBasic<TResult>(result);
                    //}//new OrmHelper().GetResult<TResult>(command.ExecuteScalar(), typeCode);
                    throw new NotSupportedException("暂不支持匿名类型");
                }
            }
        }

        public static object GetResult(TranslateResult translatResult, object obj, ProviderElement providerElement, CommandType commandType = CommandType.Text)
        {
            //Trace.WriteLine(string.Format("执行SQL:{0}", translatResult.SqlText));
            var typeCode = new OrmHelper().GetTypeCode(obj.GetType());

            if (DataAccessExecutionContext.Current == null || DataAccessExecutionContext.Current.ProviderElement.Key != providerElement.Key)
            {
                var factory = DbProviderFactories.GetFactory(providerElement.Provider);

                using (DbConnection con = factory.CreateConnection())
                {
                    con.ConnectionString = providerElement.ConnectionString;//Config.Instance.DefaultProvider.ConnectionString;
                    con.Open();
                    using (DbCommand command = con.CreateCommand())
                    {
                        command.CommandText = translatResult.SqlText;
                        command.CommandType = commandType;
                        command.Parameters.AddRange(translatResult.Parameters.ToArray());
                        if (typeCode == OrmType.KnowType || typeCode == OrmType.UnKnowType)
                        {
                            using (var reader = command.ExecuteReader())
                            {
                                if (reader.HasRows && reader.Read())
                                {
                                    var temp = new OrmHelper().GetResult(reader, obj, providerElement, typeCode);
                                    reader.Close();
                                    return temp;
                                }
                                else return null;
                            }
                        }
                        else if (typeCode == OrmType.Basic) return command.ExecuteScalar();//new OrmHelper().GetResult<TResult>(command.ExecuteScalar(), typeCode);
                        else throw new NotSupportedException("暂不支持匿名类型");
                    }
                }
            }
            else
            {
                var con = DataAccessExecutionContext.Current.DbConnection;
                if (con.State != ConnectionState.Open) con.Open();
                using (DbCommand command = con.CreateCommand())
                {
                    command.CommandText = translatResult.SqlText;
                    command.CommandType = commandType;
                    command.Transaction = DataAccessExecutionContext.Current.Transaction;
                    command.Parameters.AddRange(translatResult.Parameters.ToArray());
                    if (typeCode == OrmType.KnowType || typeCode == OrmType.UnKnowType)
                    {
                        using (var reader = command.ExecuteReader())
                        {
                            if (reader.HasRows && reader.Read())
                            {
                                var temp = new OrmHelper().GetResult(reader, obj, providerElement, typeCode);
                                reader.Close();
                                return temp;
                            }
                            else return null;
                        }
                    }
                    else if (typeCode == OrmType.Basic) return command.ExecuteScalar();//new OrmHelper().GetResult<TResult>(command.ExecuteScalar(), typeCode);
                    else throw new NotSupportedException("暂不支持匿名类型");
                }
            }
        }

        public static bool ExecuteNonQuery(TranslateResult translatResult, ProviderElement provider, CommandType commandType = CommandType.Text)
        {
            //Trace.WriteLine(string.Format("执行SQL:{0}", translatResult.SqlText));
            if (DataAccessExecutionContext.Current == null || DataAccessExecutionContext.Current.ProviderElement.Key != provider.Key)
            {
                var factory = DbProviderFactories.GetFactory(provider.Provider);
                using (DbConnection con = factory.CreateConnection())
                {
                    con.ConnectionString = provider.ConnectionString;//Config.Instance.DefaultProvider.ConnectionString;
                    if (con.State != ConnectionState.Open) con.Open();
                    using (DbCommand command = con.CreateCommand())
                    {
                        command.CommandText = translatResult.SqlText;
                        command.CommandType = commandType;
                        command.Parameters.AddRange((translatResult.Parameters as IEnumerable<DbParameter>).ToArray());
                        return command.ExecuteNonQuery() > 0;
                    }
                }
            }
            else
            {
                var temp = DataAccessExecutionContext.Current;
                if (temp.DbConnection.State == ConnectionState.Closed) temp.DbConnection.Open();
                using (DbCommand command = temp.DbConnection.CreateCommand())
                {
                    command.CommandText = translatResult.SqlText;
                    command.CommandType = commandType;
                    command.Transaction = temp.Transaction;
                    command.Parameters.AddRange((translatResult.Parameters as IEnumerable<DbParameter>).ToArray());
                    return command.ExecuteNonQuery() > 0;
                }
            }
        }

        internal static bool CodeFirstExcuteNonQuery(TranslateResult translatResult, ProviderElement provider, CommandType commandType = CommandType.Text)
        {
            DataAccessExecutionContext context = null;
            if (DataAccessExecutionContext.Current == null || DataAccessExecutionContext.Current.ProviderElement.Key != provider.Key)
            {
                context = new DataAccessExecutionContext(provider);
            }
            else
            {
                context = DataAccessExecutionContext.Current;
            }
            //var context = DataAccessExecutionContext.Current ?? new DataAccessExecutionContext(provider);
            bool flag = false;
            using (DbCommand command = context.DbConnection.CreateCommand())
            {
                command.CommandText = translatResult.SqlText;
                command.CommandType = commandType;
                command.Transaction = context.Transaction;
                command.Parameters.AddRange(translatResult.Parameters);
                flag = command.ExecuteNonQuery() > 0;
                context.Transaction.Commit();
            }
            if (DataAccessExecutionContext.Current == null 
                || DataAccessExecutionContext.Current.ProviderElement.Key != provider.Key)
                context.Dispose();
            else
                context.ResetTransaction();
            return flag;
            //var factory = DbProviderFactories.GetFactory(provider.Provider);
            //using (DbConnection con = factory.CreateConnection())
            //{
            //    con.ConnectionString = provider.ConnectionString;//Config.Instance.DefaultProvider.ConnectionString;
            //    if (con.State != ConnectionState.Open) con.Open();
            //    using (DbCommand command = con.CreateCommand())
            //    {
            //        command.CommandText = translatResult.SqlText;
            //        command.CommandType = commandType;
            //        command.Parameters.AddRange(translatResult.Parameters.ToArray());
            //        return command.ExecuteNonQuery() > 0;
            //    }
            //}
        }
    }
}
